SuperMap iClient3D for Cesium的场景效果并不限于每次打开时看到的样子,它还可以进行各种个性化的设置。比如,制作一个晴朗的天空;调出夕阳西下的光影;打造科技感城市夜景特效;展现白模的边框轮廓;优化精模的纹理效果等等。从天空的效果,到场景的光照,及模型的外观均可以进行改变或设置。
本文档从以下几个方面分别进行说明:
与天空相关的功能主要包括:天空盒,大气层,太阳光晕等。
2.1.1如何制作自定义天空盒效果
1.制作天空盒素材
图1
图2
2.使用方法
sources: { positiveX : './images/天空盒素材/晴天/Right.jpg', negativeX : './images/天空盒素材/晴天/Left.jpg', positiveY : './images/天空盒素材/晴天/Front.jpg', negativeY : './images/天空盒素材/晴天/Back.jpg', positiveZ : './images/天空盒素材/晴天/Up.jpg', negativeZ : './images/天空盒素材/晴天/Down.jpg' }
图3
在创建场景时,系统默认会创建一个星空效果的“天空盒”及围绕地球的大气层。
图4
而当我们拉近视角,进入地平面时,需要切换为天空的效果。
这里我们设置一个高度,当大于这个高度时,我们距离地球比较远,看到的是地球周围的大气层与星空;当小于这个高度时,我们距离地球比较近,就会看到天空的效果。
scene.postRender.addEventListener(function() { var cameraHeight = scene.camera.positionCartographic.height; var toggleHeight = 23e4; if(cameraHeight < toggleHeight && Cesium.defined(currentSkyBox)) { scene.skyBox = currentSkyBox; scene.skyAtmosphere.show = false; } else { scene.skyBox = defaultSkyBox; scene.skyAtmosphere.show = true; } });
图5
图6
3.注意事项
2.1.2如何更改大气层的渲染效果
1.快速改变大气层的渲染效果
设置viewer.scene.globe.enableLighting = true;同时开启时间轴,通过改变时间,即可快速调整大气层的效果。
开启时间轴代码如下
function onload(Cesium) { var viewer = new Cesium.Viewer('cesiumContainer', { timeline: true }); }
图7
2.自定义控制大气层的渲染效果效果
如何制作一个暖色调的大气层?通过控制大气层的色相向橙黄色偏移,同时降低其亮度及饱和度。如果还想让星辰若隐若现,还可以降低大气层的透明度。
//开启大气层 scene.skyAtmosphere.show =true; //修改大气层的亮度 scene.skyAtmosphere.brightnessShift=0.1; //修改大气层的色调 scene.skyAtmosphere.hueShift=0.5; //修改大气层的饱和度 scene.skyAtmosphere.saturationShift =0.1; //修改大气层的透明度 scene.skyAtmosphere.alpha =0.8;
图8
图9
2.1.3如何改变太阳的显示效果
这里所说的太阳的显示效果,是指改变太阳的“外观”,而不是改变它发射出来的“光线”。通过调整scene.sun.glowFactor的值来实现。
图10
在SuperMap iClient3D for Cesium中,场景中默认存在两个光源:
二者共同决定了场景中的光照效果。
2.2.1如何调整环境光的效果
环境光是从四周发射光线来照亮场景的,没有方向性。常见的需要调节环境光的场景有以下三种:
下图所示的场景中,就是设置了一个很低值环境光的效果(为了突显模型上的自发光纹理效果),设置
scene.lightSource.ambientLightColor = new Cesium.Color(0.1, 0.1, 0.1, 0.1)
图11
2.2.2修改光线后没有起作用
如果场景中的对象是以entity的方式添加的glTF模型,调整太阳光及环境光之后,模型的光照效果时没有变化的。那么如果想要制作一个夜景的效果要怎么设置?可以通过修改imageBasedLightingFactor的值来调整。
var gltf1 = viewer.entities.add({ name: "gltf", position: new Cesium.Cartesian3.fromDegrees(xxx,yyy, 0), model: { uri: "../data(范例)/04-临时测试/Gltf/name.gltf" } }); var imageBasedLightingFactor = new Cesium.Cartesian2(0.1, 0.1); gltf1.model.imageBasedLightingFactor = imageBasedLightingFactor; viewer.zoomTo(gltf1);
在SuperMap iClient3D for Cesium中,支持自定义设置光源,可以添加的光源类型有:平行光,点光源,聚光灯。
2.3.1利用自定义的平行光优化白模的显示效果
如下图所示,通过添加自定义的平行光制作一个更具设计感的白模效果。
图12
场景光线调整思路:
具体调整方法及参数设置:
1.修改默认光照的参数
关闭太阳光,调暗环境光,给一个较亮的大气层效果。
//默认场景设置 //设置太阳是否开启--关闭太阳光 scene.sun.show = false; //设置环境光的强度 scene.lightSource.ambientLightColor = new Cesium.Color(0.5, 0.5, 0.5, 1); //修改大气层的亮度 scene.skyAtmosphere.brightnessShift=0.4;
2.添加自定义的平行光光源
//添加光源 //东南45方向 //光源的倾角比较平,使得路面与桥墩的对比度比较高。 var position1 = new Cesium.Cartesian3.fromDegrees(xxx,yyy, 445); var targetPosition1 = new Cesium.Cartesian3.fromDegrees(xxz, yyz,430); var dirLightOptions = { targetPosition: targetPosition1, color: new Cesium.Color(0.8, 0.8, 0.8, 1), intensity: 1 }; directionalLight_1 = new Cesium.DirectionalLight(position1, dirLightOptions); scene.addLightSource(directionalLight_1);
其中,position1为光源的位置,targetPosition1为光源的目标点,二者决定了光线的角度。
2.3.2利用自定义的平行光优化精模的显示效果
精模不同于白模,在还原纹理的基础上,更好的展现模型的立体效果。
如下图所示,进行说明。
图13
场景光线调整思路:
1.修改默认光照的参数
关闭太阳光,稍微调暗环境光。
//默认场景设置 //设置太阳是否开启--关闭太阳光 scene.sun.show = false; //设置环境光的强度 scene.lightSource.ambientLightColor = new Cesium.Color(0.65, 0.65, 0.65, 1); //修改大气层的亮度 scene.skyAtmosphere.brightnessShift=0.4;
2.添加自定义的平行光光源
//添加光源 //东南45方向 光线倾角25°左右 var position1 = new Cesium.Cartesian3.fromDegrees(xxx,yyy,, 480); var targetPosition1 = new Cesium.Cartesian3.fromDegrees(xxz,yyz,,430); var dirLightOptions = { targetPosition: targetPosition1, color: new Cesium.Color(1.0, 1.0, 1.0, 1), intensity: 0.55 }; directionalLight_1 = new Cesium.DirectionalLight(position1, dirLightOptions); scene.addLightSource(directionalLight_1);
2.3.3利用自定义光源制作城市夜景特效
如下图所示,进行说明。
图14
1.因为是夜景,首先关闭太阳光与环境光。
scene.sun.show = false; scene.lightSource.ambientLightColor = new Cesium.Color(0, 0, 0, 1);
2.给场景添加一个平行光和点光源作为底光
平行光位置不限,保证整个场景都能有一个偏蓝的色调。点光源的置于重点建筑群附近,提升该区域的亮度,作为整个场景的视觉中心区域。
// 新增直射光-整个环境 var dirLightOptions = { targetPosition: targetPosition1, color: new Cesium.Color(0.01, 0.01, 0.3, 1.0), intensity: 0.1 }; // 新增点光源-整个环境 var pointLightOptions3 = { cutoffDistance: 2000, color: new Cesium.Color(0.04, 0.18, 0.43, 1.0), intensity: 0.001 };
3.依次给重点建筑单独打造灯光效果
这里以场景中的最高楼-国贸大厦为例,在其周围添加多个点光源,并设置光源颜色为偏青蓝色的冷色调。点光源的高度大致位于80米处,以打亮建筑的中下部分。
并用同样的方法给其它重点建筑添加灯光效果。
// 新增点光源-建筑 var pointLightPoszuigao1 = new Cesium.Cartesian3.fromDegrees(xxx, yyy, 80.0); var pointLightOptionszuigao1 = { cutoffDistance: 360.0, color: new Cesium.Color(0.15, 0.45, 1.4, 1.0), intensity: 0.12 }; pointLightzuigao1 = new Cesium.PointLight(pointLightPoszuigao1, pointLightOptionszuigao1); scene.addLightSource(pointLightzuigao1); var pointLightPoszuigao2 = new Cesium.Cartesian3.fromDegrees(xxx, yyy, 80.0); pointLightzuigao2 = new Cesium.PointLight(pointLightPoszuigao2, pointLightOptionszuigao1); scene.addLightSource(pointLightzuigao2); var pointLightPoszuigao3 = new Cesium.Cartesian3.fromDegrees(xxx, yyy, 80.0); pointLightzuigao3 = new Cesium.PointLight(pointLightPoszuigao3, pointLightOptionszuigao1); scene.addLightSource(pointLightzuigao3); var pointLightPoszuigao4 = new Cesium.Cartesian3.fromDegrees(xxx, yyy, 80.0); pointLightzuigao4 = new Cesium.PointLight(pointLightPoszuigao4, pointLightOptionszuigao1); scene.addLightSource(pointLightzuigao4);
4.给道路添加路灯效果。
前面添加的灯光都是针对建筑添加的,道路上面也会有很多的路灯。
这里通过聚光灯来模拟路灯的效果,因为路灯具有明显的方向性。因为之前添加的灯光都是冷色调的,这里给路灯设置一个比较明显的暖色调,平衡场景中的颜色分布。
因为场景是支持HDR的,所以可以给光源颜色设置大于1的RGB值(6, 5, 0.2, 1)。另外给光源设置一个合适的衰减系数(3),保证灯光在向周围传播的时候逐渐减弱。
至此,灯光系统的添加基本完成。
// 新增聚光灯-横向道路-路灯1 var spotLightPosludeng1_1 = new Cesium.Cartesian3.fromDegrees(xxx, yyy, 30); var spotLightTargetPosludeng1_1 = new Cesium.Cartesian3.fromDegrees(xxx, yyy, 0); var spotLightOtionsludeng1_1 = { color: new Cesium.Color(6, 5, 0.2, 1), distance: 100, decay: 3, intensity: 13, angle: Math.PI / 2 }; spotLightludeng1_1 = new Cesium.SpotLight(spotLightPosludeng1_1, spotLightTargetPosludeng1_1, spotLightOtionsludeng1_1); scene.addLightSource(spotLightludeng1_1); // 新增聚光灯-横向道路-路灯2 var spotLightPosludeng1_2 = new Cesium.Cartesian3.fromDegrees(xxx, yyy, 30); var spotLightTargetPosludeng1_2 = new Cesium.Cartesian3.fromDegrees(xxx, yyy, 0); spotLightludeng1_2 = new Cesium.SpotLight(spotLightPosludeng1_2, spotLightTargetPosludeng1_2, spotLightOtionsludeng1_1); scene.addLightSource(spotLightludeng1_2); // 新增聚光灯-横向道路-路灯3 var spotLightPosludeng1_3 = new Cesium.Cartesian3.fromDegrees(xxx, yyy, 30); var spotLightTargetPosludeng1_3 = new Cesium.Cartesian3.fromDegrees(xxx, yyy, 0); spotLightludeng1_3 = new Cesium.SpotLight(spotLightPosludeng1_3, spotLightTargetPosludeng1_3, spotLightOtionsludeng1_1); scene.addLightSource(spotLightludeng1_3);
注:
HDR全称High Dynamic Range(高动态范围图像),是采用更大的动态范围进行照明计算从而对画面图形进行渲染。
如果没有HDR,那么太暗的模型将会直接融入黑色环境,太亮的模型则直接显示为白色,缺少了色彩的渐变效果。
HDR可以保证亮的地方非常亮,暗的地方非常暗,同时亮暗部的细节都很明显。
只有在HDR模式下,场景中的光比才更加真实,光源及自发光纹理才能有正确的显示效果。
比如,在有特效的场景中,通过设置多个光源及纹理自发光等,来表达不同区域之间丰富的明暗变化与光影效果,此时建议开启HDR模式。如果场景中只有太阳光,环境光等比较单一的光源,场景对象受光比较均匀,则没有必要开启HDR。
图15
图16
有时会碰到带有两重纹理的模型,其中一层是常见的决定模型外观的漫反射纹理,另外一层则是制造模型光影明暗的烘焙纹理(一般通过3ds Max里面的烘焙功能制作)。在SuperMap iClient3D for Cesium中,提供了一个默认的参数(scene.shadowMap.darkness)来决定二者的叠加效果,来满足大多数的需求,如果想要自定义二者的叠加效果,可以对该参数进行修改。
如图所示,在同样的光照条件下,上图设置darkness的值为1.0,整体场景的亮度稍低,并且色调偏黄偏红;下图设置darkness的值为1.275,整体场景的亮度有所提升,并且消除了原有的偏色现象,与原始模型的效果相比,还原度更高。
图17
图18
2.6.1场景颜色的调整
SuperMap iClient3D for Cesium中,提供了用于修改场景颜色的一系列参数:亮度,对比度,色调,饱和度等。修改该参数时,场景中的所有对象均发生改变。
具体用法及效果可参考在线范例:http://support.supermap.com.cn:8090/SuperMap3D/examples/SuperMap3D/editor.html#colorCorrection
2.6.2图层颜色的调整
如果要对场景中的某一个或者某些图层单独做调整,可以使用图层颜色校正功能。如图所示,单独对树木图层的色调进行修改(色调值由0调整为-1),将秋天的树木“修改”为夏天的树木。设置代码如下:
var layer1 = scene.layers.find("c树木11640@鸟巢"); layer1.hue = -1; layer1.brightness= 1; layer1.contrast = 1;
图19
图20
在SuperMap iClient3D for Cesium中支持开启硬件反走样,用于提升模型的显示效果,尤其是电力塔,栅栏,路灯等细长、有镂空的模型,优化效果更明显。硬件反走样开启方法:初始化viewer部件时,在contextOptions属性中,设置requestSuperMap3D2为true,msaaLevel值为2-8,具体代码设置如下。
var viewer = new Cesium.Viewer('cesiumContainer',{ //反走样 contextOptions:{ //硬件反走样,默认值为1 msaaLevel:8, requestSuperMap3D2:true } }),
图21
在设计类软件中,常常通过显示模型的边框线来优化模型的显示效果,使其更有设计感,因此在SuperMap iClient3D for Cesium上优化了线的绘制效果。这里以填充和线框模式为例进行说明,默认线框的颜色为深灰色,并可根据需要修改颜色,代码设置如下。
layer.style3D.fillStyle = Cesium.FillStyle.Fill_And_WireFrame; layer.wireFrameMode = Cesium.WireFrameType.EffectOutline;
具体用法及效果可参考在线范例:http://support.supermap.com.cn:8090/SuperMap3D/examples/SuperMap3D/editor.html#wireframe
图22
如何在SuperMap iClient3D for Cesium的平面场景中添加自定义光源。
平面场景中,是支持自定义的光源的,只是添加光源的位置坐标需要是Cartesian3。
1.如果数据本身是平面的数据,发布服务之后,直接通过SuperMap iClient3D for Cesium打开,默认既是平面的场景。
添加自定义光源时,使用的坐标,不能使用Supermap iDesktop打开平面数据,再通过坐标查询得到的坐标,要使用前端查询获取的坐标。
坐标查询方式:
//拾取点击点的坐标 var screenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler(scene.canvas); screenSpaceEventHandler.setInputAction(function (evt) { var cartesian = scene.pickPosition(evt.position); console.log(cartesian); }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
光源添加方式:
var position1 = new Cesium.Cartesian3( 5522423.797161465, 460702.87773946195, 3157843.5904182503); var targetPosition1 = new Cesium.Cartesian3(5522375.5857076915, 460656.85253924195,3157986.9535061973); var dirLightOptions = { targetPosition: targetPosition1, color: new Cesium.Color(1.0, 1.0, 1.0, 1), // color: new Cesium.Color(1.0, 1.0, 1.0, 1), intensity: 1.55 }; directionalLight_1 = new Cesium.DirectionalLight(position1, dirLightOptions); scene.addLightSource(directionalLight_1);
2.如果数据本身是球面的数据,只需要在打开的时候,设置下打开的方式,即可将数据添加到平面场景中,
//平面场景 viewer.scene.mode = Cesium.SceneMode.COLUMBUS_VIEW; //打开场景 scene.open(URL_CONFIG.SCENE_CBD);
并且光源的添加方式有两种:
// 新增聚光灯 var spotLightPosludeng1_1 = new Cesium.Cartesian3(-2179640.6821754016,4379810.971923672, 4092349.589765973); var spotLightTargetPosludeng1_1 = new Cesium.Cartesian3(-2179672.0304557816, 4379901.146983794, 4092488.1975491447); var spotLightOtionsludeng1_1 = { color: new Cesium.Color(6, 4, 0.2, 1), distance: 550, decay: 1, intensity: 9, angle: Math.PI / 2 }; spotLightludeng1_1 = new Cesium.SpotLight(spotLightPosludeng1_1, spotLightTargetPosludeng1_1, spotLightOtionsludeng1_1); scene.addLightSource(spotLightludeng1_1);
var position1 = new Cesium.Cartesian3.fromDegrees(116.261209157595+0.000009405717451407729*70.7, 39.3042238956531-0.00000914352698135*70.7, 480); //光源方向点 var targetPosition1 = new Cesium.Cartesian3.fromDegrees(116.261209157595, 39.3042238956531,430); var dirLightOptions = { targetPosition: targetPosition1, color: new Cesium.Color(1.0, 1.0, 1.0, 1), // color: new Cesium.Color(1.0, 1.0, 1.0, 1), intensity: 0.55 }; directionalLight_1 = new Cesium.DirectionalLight(position1, dirLightOptions); scene.addLightSource(directionalLight_1);